package com.nongcai159.mall.lib_common.utils

import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Process
import android.widget.Toast
import java.io.BufferedWriter
import java.io.FileWriter
import java.io.IOException
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.*

/**
 * 错误信息写入文件
 *
 *
 * Created by tanbiheng on 2017/10/17.
 */

class CrashHandler private constructor() : Thread.UncaughtExceptionHandler {
    private var mDefaultCrashHandler: Thread.UncaughtExceptionHandler? = null
    private var mContext: Context? = null

    fun init(context: Context) {
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler()
        Thread.setDefaultUncaughtExceptionHandler(this)
        mContext = context.applicationContext
    }

    /**
     * 这个是最关键的函数，当程序中有未被捕获的异常，系统将会自动调用uncaughtException方法
     * thread为出现未捕获异常的线程，ex为未捕获的异常，有了这个ex，我们就可以得到异常信息
     *
     * @param thread
     * @param ex
     */

    override fun uncaughtException(thread: Thread, ex: Throwable) {
        try {
            //导出异常信息到SD卡中
            dumpExceptionToSDCard(ex)
        } catch (e: IOException) {
            e.printStackTrace()
        }

        ex.printStackTrace()
        //如果系统提供默认的异常处理器，则交给系统去结束程序，否则就由自己结束自己
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler!!.uncaughtException(thread, ex)
        } else {
            //自己处理
            try {//延迟3秒杀进程
                Thread.sleep(2000)
                Toast.makeText(mContext, "~程序出错了~", Toast.LENGTH_SHORT).show()
            } catch (e: InterruptedException) {
                MLog.e("error : ", e)
            }

            Process.killProcess(Process.myPid())
        }
    }

    @Throws(IOException::class)
    private fun dumpExceptionToSDCard(ex: Throwable) {
        if (!FileUtils.isFileExist(FileUtils.CRASH_DIR)) {
            return
        }

        val current = System.currentTimeMillis()
        val time = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss").format(Date(current))
        val crashPath = FileUtils.CRASH_DIR + FILE_NAME + time + FILE_NAME_SUFFIX
        val file = FileUtils.createFile(crashPath)

        try {
            val pw = PrintWriter(BufferedWriter(FileWriter(file!!)))
            pw.println(time)
            pw.println()
            dumpPhoneInfo(pw)
            pw.println()
            ex.printStackTrace(pw)
            pw.close()
            MLog.e("dump crash info success")
        } catch (e: Exception) {
            MLog.e(e.message!!)
            MLog.e("dump crash info failed")
        }

    }

    @Throws(PackageManager.NameNotFoundException::class)
    private fun dumpPhoneInfo(pw: PrintWriter) {
        val pm = mContext!!.packageManager
        val pi = pm.getPackageInfo(mContext!!.packageName,
                PackageManager.GET_ACTIVITIES)
        pw.print("app版本: ")
        pw.print(pi.versionName)
        pw.print("_")
        pw.println(pi.versionCode)
        pw.println()

        //Android版本号
        pw.print("系统版本: ")
        pw.print(Build.VERSION.RELEASE)
        pw.print("_")
        pw.println(Build.VERSION.SDK_INT)
        pw.println()

        //手机制造商
        pw.print("手机制造商: ")
        pw.println(Build.MANUFACTURER)
        pw.println()

        //手机型号
        pw.print("手机型号: ")
        pw.println(Build.MODEL)
        pw.println()

        //CPU架构
        pw.print("CPU_ABI: ")
        pw.println(Build.CPU_ABI)
        pw.println()
    }

    companion object {
        private val FILE_NAME = "crash_"
        private val FILE_NAME_SUFFIX = ".txt"

        private val INSTANCE = CrashHandler()

        fun getInstance(): CrashHandler {
            return INSTANCE
        }
    }
}
